#include "in.h"

/* for testing
carmela_broker.do stop
carmela_broker.do stop ; sleep 1 ; rmlog ; carmela_broker.do start --tcp-nodelay --log-level DEBUG

carmela_broker.do stop ; sleep 1 ; rmlog ; carmela_broker.do start --tcp-nodelay --log-level DEBUG \
	--msg-file-size 200 --msg-file-list-nodes-soft-max 1 --msg-file-list-nodes-hard-max 2 \
	--topic-file-size 100 --topic-file-list-nodes-soft-max 1 --topic-file-list-nodes-hard-max 2

carmela_broker.do stop ; sleep 1 ; rmlog ; carmela_broker.do start --tcp-nodelay --log-level DEBUG \
	--timeout 30 --heartbeat 10

carmela_broker.do stop ; sleep 1 ; rmlog ; carmela_broker.do start --tcp-nodelay --log-level ERROR

carmela_broker.do stop ; sleep 1 ; rmlog ; carmela_broker.do start --tcp-nodelay --log-level DEBUG \
	--delay-msg-file-size 200 --delay-msg-file-list-nodes-soft-max 1
*/

static void usage()
{
	printf( "carmela_broker v%s\n" , __CARMELA_VER );
	printf( "Copyright by calvin 2021\n" );
	printf( "USAGE : carmela_broker [ --ip broker_ip ]\n" );
	printf( "                       [ --port broker_port ]\n" );
	printf( "                       [ --tcp-nodelay ]\n" );
	printf( "                       [ --timeout (seconds) ]\n" );
	printf( "                       [ --heartbeat (seconds) ]\n" );
	printf( "                       [ --data-path (mq data files path , default for $HOME/amqdata , make directory automatically) ]\n" );
	printf( "                       [ --msg-file-size (size) ]\n" );
	printf( "                       [ --topic-file-size (size) ]\n" );
	printf( "                       [ --delay-msg-file-size (size) ]\n" );
	printf( "                       [ --msg-file-list-nodes-soft-max (count) ]\n" );
	printf( "                       [ --msg-file-list-nodes-hard-max (count) ]\n" );
	printf( "                       [ --topic-file-list-nodes-soft-max (count) ]\n" );
	printf( "                       [ --topic-file-list-nodes-hard-max (count) ]\n" );
	printf( "                       [ --delay-msg-file-list-nodes-soft-max (count) ]\n" );
	printf( "                       [ --log-pathfilenname (default for $HOME/log/carmela_broker.log) ]\n" );
	printf( "                       [ --log-level (DEBUG|INFO|WARN:default|ERROR|FATAL) ]\n" );
	printf( "                       [ --no-daemon ]\n" );
	return;
}

int main( int argc , char *argv[] )
{
	struct MQBroker	broker ;
	int			i ;
	char			*env_MQ_TCP_NODEALY = NULL ;
	char			*env_MQ_BROKER_TCP_NODEALY = NULL ;
	
	int			nret = 0 ;
	
	if( argc == 1 + 1 && STRCMP( argv[1] , == , "?" ) )
	{
		usage();
		exit(1);
	}
	
	memset( & broker , 0x00 , sizeof(struct MQBroker) );
	strncpy( broker.entry.ip , MQ_BROKER_IP_DEFAULT , sizeof(broker.entry.ip)-1 );
	broker.entry.port = MQ_BROKER_PORT_DEFAULT ;
	broker.entry.timeout_mode = TCPDAEMON_RECV_TIMEOUT_MODE ;
	broker.entry.timeout_seconds = MQ_BROKER_TIMEOUT_DEFAULT ;
	broker.entry.idletimer_interval = MQ_BROKER_HEARTBEAT_DEFAULT ;
	snprintf( broker.data_path , sizeof(broker.data_path)-1 , "%s/%s" , getenv("HOME") , MQ_BROKER_DATA_PATH_DEFAULT );
	env_MQ_TCP_NODEALY = getenv( "MQ_TCP_NODELAY" ) ;
	env_MQ_BROKER_TCP_NODEALY = getenv( "MQ_BROKER_TCP_NODELAY" ) ;
	if( ( env_MQ_TCP_NODEALY && atoi(env_MQ_TCP_NODEALY) ) || ( env_MQ_BROKER_TCP_NODEALY && atoi(env_MQ_BROKER_TCP_NODEALY) ) )
		broker.tcp_nodelay = 1 ;
	broker.msg_file_size = MQ_MSG_FILE_SIZE_DEFAULT ;
	broker.topic_file_size = MQ_TOPIC_FILE_SIZE_DEFAULT ;
	broker.delay_msg_file_size = MQ_DELAY_MSG_FILE_SIZE_DEFAULT ;
	broker.msg_file_list_nodes_soft_max = MSG_FILE_LIST_NODES_COUNT_SOFT_MAX_DEFAULT ;
	broker.msg_file_list_nodes_hard_max = MSG_FILE_LIST_NODES_COUNT_HARD_MAX_DEFAULT ;
	broker.topic_file_list_nodes_soft_max = TOPIC_FILE_LIST_NODES_COUNT_SOFT_MAX_DEFAULT ;
	broker.topic_file_list_nodes_hard_max = TOPIC_FILE_LIST_NODES_COUNT_HARD_MAX_DEFAULT ;
	broker.delay_msg_file_list_nodes_soft_max = DELAY_MSG_FILE_LIST_NODES_COUNT_SOFT_MAX_DEFAULT ;
	snprintf( broker.entry.log_pathfilename , sizeof(broker.entry.log_pathfilename)-1 , "%s/log/carmela_broker.log" , getenv("HOME") );
	broker.entry.log_level = LOGLEVEL_WARN ;
	broker.entry.daemon_level = 1 ;
	
	for( i = 1 ; i < argc ; i++ ) 
	{
		if( STRCMP( argv[i] , == , "--ip" ) && i+1 < argc )
		{
			i++;
			strncpy( broker.entry.ip , argv[i] , sizeof(broker.entry.ip)-1 );
		}
		else if( STRCMP( argv[i] , == , "--port" ) && i+1 < argc )
		{
			i++;
			broker.entry.port = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--tcp-nodelay" ) )
		{
			broker.tcp_nodelay = 1 ;
		}
		else if( STRCMP( argv[i] , == , "--timeout" ) && i+1 < argc )
		{
			i++;
			broker.entry.timeout_mode = TCPDAEMON_RECV_TIMEOUT_MODE ;
			broker.entry.timeout_seconds = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--heartbeat" ) && i+1 < argc )
		{
			i++;
			broker.entry.idletimer_interval = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--data-path" ) && i+1 < argc )
		{
			i++;
			strncpy( broker.data_path , argv[i] , sizeof(broker.data_path)-1 );
		}
		else if( STRCMP( argv[i] , == , "--msg-file-size" ) && i+1 < argc )
		{
			i++;
			broker.msg_file_size = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--topic-file-size" ) && i+1 < argc )
		{
			i++;
			broker.topic_file_size = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--delay-msg-file-size" ) && i+1 < argc )
		{
			i++;
			broker.delay_msg_file_size = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--msg-file-list-nodes-soft-max" ) && i+1 < argc )
		{
			i++;
			broker.msg_file_list_nodes_soft_max = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--msg-file-list-nodes-hard-max" ) && i+1 < argc )
		{
			i++;
			broker.msg_file_list_nodes_hard_max = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--topic-file-list-nodes-soft-max" ) && i+1 < argc )
		{
			i++;
			broker.topic_file_list_nodes_soft_max = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--topic-file-list-nodes-hard-max" ) && i+1 < argc )
		{
			i++;
			broker.topic_file_list_nodes_hard_max = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--delay-msg-file-list-nodes-soft-max" ) && i+1 < argc )
		{
			i++;
			broker.delay_msg_file_list_nodes_soft_max = atoi(argv[i]) ;
		}
		else if( STRCMP( argv[i] , == , "--log-pathfile" ) && i+1 < argc )
		{
			i++;
			strncpy( broker.entry.log_pathfilename , argv[i] , sizeof(broker.entry.log_pathfilename)-1 );
		}
		else if( STRCMP( argv[i] , == , "--log-level" ) && i+1 < argc )
		{
			i++;
			broker.entry.log_level = ConvertLogLevel_atoi(argv[i]) ;
			if( broker.entry.log_level < 0 )
			{
				printf( "ERROR : invalid command value[%s] for '--log-level'\n" , argv[i] );
				usage();
				exit(7);
			}
		}
		else if( STRCMP( argv[i] , == , "--no-daemon" ) && i+1 < argc )
		{
			broker.entry.daemon_level = 0 ;
		}
		else
		{
			printf( "ERROR : invalid command option[%s]\n" , argv[i] );
			usage();
			exit(7);
		}
	}
	
	INFOLOG( "broker.entry.ip[%s]" , broker.entry.ip );
	INFOLOG( "broker.entry.port[%d]" , broker.entry.port );
	INFOLOG( "broker.entry.timeout_mode[%c]" , broker.entry.timeout_mode );
	INFOLOG( "broker.entry.timeout_seconds[%d]" , broker.entry.timeout_seconds );
	INFOLOG( "broker.entry.idletimer_interval[%d]" , broker.entry.idletimer_interval );
	INFOLOG( "broker.data_path[%s]" , broker.data_path )
	if( access( broker.data_path , F_OK ) == -1 )
	{
		if( mkdir( broker.data_path , S_IRWXU ) == -1 )
		{
			printf( "ERROR : mkdir '%s' failed , errno[%d]\n" , broker.data_path , errno );
			ERRORLOG( "mkdir '%s' failed , errno[%d]" , broker.data_path , errno )
			exit(1);
		}
	}
	if( access( broker.data_path , W_OK ) == -1 )
	{
		printf( "ERROR : access '%s' unable to write\n" , broker.data_path );
		ERRORLOG( "access '%s' unable to write" , broker.data_path )
		exit(1);
	}
	INFOLOG( "broker.msg_file_list_nodes_soft_max[%zu]" , broker.msg_file_list_nodes_soft_max )
	INFOLOG( "broker.msg_file_list_nodes_hard_max[%zu]" , broker.msg_file_list_nodes_hard_max )
	INFOLOG( "broker.topic_file_list_nodes_soft_max[%zu]" , broker.topic_file_list_nodes_soft_max )
	INFOLOG( "broker.topic_file_list_nodes_hard_max[%zu]" , broker.topic_file_list_nodes_hard_max )
	INFOLOG( "broker.delay_msg_file_list_nodes_soft_max[%zu]" , broker.delay_msg_file_list_nodes_soft_max )
	printf( "Output log to %s\n" , broker.entry.log_pathfilename );
	printf( "Set log level %s\n" , g_log_level_itoa[broker.entry.log_level] );
	MQSetLogEnv( broker.entry.log_level , broker.entry.log_pathfilename );
	
	nret = LoadAllMessageStores( & broker ) ;
	if( nret )
	{
		printf( "LoadAllMessageStore failed[%d]\n" , nret );
		ERRORLOG( "LoadAllMessageStore failed[%d]" , nret )
		exit(1);
	}
	else
	{
		printf( "Load all message store ok\n" );
		INFOLOG( "Load all message store ok" )
	}
	
	printf( "carmela_broker start ...\n" );
	
	strcpy( broker.entry.server_model , "IOMP" );
	broker.entry.process_count = 1 ;
	broker.entry.pfunc_tcpmain = tcpmain ;
	broker.entry.param_tcpmain = (void*) & broker ;
	
	return -tcpdaemon( & (broker.entry) );
}

